在k8s上部署ClickHouse

您所在的位置:网站首页 clickhouse 使用变量 在k8s上部署ClickHouse

在k8s上部署ClickHouse

2024-07-17 14:37:52| 来源: 网络整理| 查看: 265

概述

clickhouse的容器化部署,已经有非常成熟的生态了。在一些互联网大厂也已经得到了大规模的应用。

clickhouse作为一款数据库,其容器化的主要难点在于它是有状态的服务,因此,我们需要配置PVC。

目前业界比较流行的部署方式有两种:

kubectl 原生部署 这种方式部署流程复杂,需要管理的资源非常多,稍不留神就容易出错维护繁琐,涉及到集群的扩缩容、rebalance等操作会很复杂非常不推荐这种部署方式kubectl + operator部署 资源集中管理,部署方便维护方便业界已经有成熟的方案,如 clickhouse-operator、RadonDB clickhouse等。

本文以 clickhouse-operator为例,来讲解clickhouse容器化的步骤以及注意事项。

clickhouse容器化部署 clickhouse-operator部署

我们可以直接下载clickhouse-operator的yaml文件用于部署。

文件路径如下:

https://raw.githubusercontent.com/Altinity/clickhouse-operator/master​raw.githubusercontent.com/Altinity/clickhouse-operator/master/deploy/operator/clickhouse-operator-install-bundle.yaml

直接使用kubectl 应用上述yaml文件:

su01:~/chenyc/ck # kubectl apply -f clickhouse-operator-install-bundle.yaml kubectl apply -f clickhouse-operator-install-bundle.yaml customresourcedefinition.apiextensions.k8s.io/clickhouseinstallations.clickhouse.altinity.com created customresourcedefinition.apiextensions.k8s.io/clickhouseinstallationtemplates.clickhouse.altinity.com created customresourcedefinition.apiextensions.k8s.io/clickhouseoperatorconfigurations.clickhouse.altinity.com created serviceaccount/clickhouse-operator created clusterrole.rbac.authorization.k8s.io/clickhouse-operator-kube-system created clusterrolebinding.rbac.authorization.k8s.io/clickhouse-operator-kube-system created configmap/etc-clickhouse-operator-files created configmap/etc-clickhouse-operator-confd-files created configmap/etc-clickhouse-operator-configd-files created configmap/etc-clickhouse-operator-templatesd-files created configmap/etc-clickhouse-operator-usersd-files created secret/clickhouse-operator created deployment.apps/clickhouse-operator created service/clickhouse-operator-metrics created

运行成功后,可以看到以下信息:

su01:~/chenyc/ck # kubectl get crd |grep clickhouse.altinity.com clickhouseinstallations.clickhouse.altinity.com 2023-11-16T09:41:08Z clickhouseinstallationtemplates.clickhouse.altinity.com 2023-11-16T09:41:08Z clickhouseoperatorconfigurations.clickhouse.altinity.com 2023-11-16T09:41:08Z su01:~/chenyc/ck # kubectl get pod -n kube-system |grep clickhouse clickhouse-operator-7ff755d4df-9bcbd 2/2 Running 0 10d

看到如上信息,说明operator部署成功。

快速验证

我们从官网repo里找到一个最简单的单节点部署案例:

apiVersion: "clickhouse.altinity.com/v1" kind: "ClickHouseInstallation" metadata: name: "simple-01" spec: configuration: clusters: - name: "simple"

应用部署:

kubectl apply -f ck-sample.yaml

查询状态:

chenyc@su01:~/chenyc/ch> kubectl get pod NAME READY STATUS RESTARTS AGE chi-simple-01-simple-0-0-0 1/1 Running 0 63s

尝试登录该节点:

chenyc@su01:~/chenyc/ch> kubectl exec -it chi-simple-01-simple-0-0-0 -- clickhouse-client ClickHouse client version 23.10.5.20 (official build). Connecting to localhost:9000 as user default. Connected to ClickHouse server version 23.10.5 revision 54466. Warnings: * Linux transparent hugepages are set to "always". Check /sys/kernel/mm/transparent_hugepage/enabled * Delay accounting is not enabled, OSIOWaitMicroseconds will not be gathered. Check /proc/sys/kernel/task_delayacct chi-simple-01-simple-0-0-0.chi-simple-01-simple-0-0.default.svc.cluster.local :)

登陆成功,说明部署没有问题。

但是这种部署方式有一个问题,就是外部无法访问。

service暴露外部IP端口

我们看它的service信息:

chenyc@su01:~/chenyc/ch> kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE chi-simple-01-simple-0-0 ClusterIP None 9000/TCP,8123/TCP,9009/TCP 16m clickhouse-simple-01 LoadBalancer 10.103.187.96 8123:30260/TCP,9000:32685/TCP 16m kubernetes ClusterIP 10.96.0.1 443/TCP 14d

可以看到,它默认使用了LoadBalancer的service,而且它的EXTERNAL-IP是pending状态,这是因为clickhouse-operator默认我们在云环境上使用,在私服部署的话,我们并没有提供一个负载均衡器,因此无法选择IP,导致无法访问。

这时有两种解决方案:

安装一个负载均衡器,如metallb改成nodePort方式

我们先看第一种方式,安装metallb。安装步骤大家可自行网上搜索,安装成功后如下所示:

su01:~/chenyc/ck # kubectl get pod -n metallb-system NAME READY STATUS RESTARTS AGE controller-595f88d88f-mmmfq 1/1 Running 2 146d speaker-5n4qh 1/1 Running 5 (14d ago) 146d speaker-f4pgr 1/1 Running 9 (14d ago) 146d speaker-qcfl2 1/1 Running 5 (14d ago) 146d

我们再次部署, 可以看到他给我们分配了一个192.168.110.198的IP, 注意,这个IP是真实存在的,也就是说,一定要有可分配的IP,才能成功。

su01:~/chenyc/ck # kubectl get pod NAME READY STATUS RESTARTS AGE chi-simple-01-simple-0-0-0 1/1 Running 0 71s su01:~/chenyc/ck/ch # kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE chi-simple-01-simple-0-0 ClusterIP None 9000/TCP,8123/TCP,9009/TCP 11s ckman NodePort 10.105.69.159 38808:38808/TCP 4d23h clickhouse-simple-01 LoadBalancer 10.100.12.57 192.168.110.198 8123:61626/TCP,9000:20461/TCP 8s kubernetes ClusterIP 10.96.0.1 443/TCP 14d

验证该IP是否可用:

su01:~/chenyc/ck # curl http://192.168.110.198:8123 Ok.

但是现在我们是不能从外部直接访问到这个clickhouse节点的。原因我们后面再说。

先看另一种解决方式,通过nodePort的方式来暴露端口。chi这个资源里提供了修改service的模板,修改如下:

apiVersion: "clickhouse.altinity.com/v1" kind: "ClickHouseInstallation" metadata: name: "svc" spec: defaults: templates: serviceTemplate: service-template templates: serviceTemplates: - name: service-template generateName: chendpoint-{chi} spec: ports: - name: http port: 8123 nodePort: 38123 targetPort: 8123 - name: tcp port: 9000 nodePort: 39000 targetPort: 9000 type: NodePort

此时查看service,得到如下结果:

su01:~/chenyc/ck/ch # kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE chendpoint-svc NodePort 10.111.132.229 8123:38123/TCP,9000:39000/TCP 21s chi-svc-cluster-0-0 ClusterIP None 9000/TCP,8123/TCP,9009/TCP 23s ckman NodePort 10.105.69.159 38808:38808/TCP 5d3h kubernetes ClusterIP 10.96.0.1 443/TCP 14d

同样,我们验证一下:

su01:~/chenyc/ck/ch # curl http://10.111.132.229:8123 Ok. su01:~/chenyc/ck/ch # curl http://192.168.110.186:38123 Ok. su01:~/chenyc/ck/ch # curl http://192.168.110.187:38123 Ok. su01:~/chenyc/ck/ch # curl http://192.168.110.188:38123 Ok.

上例中,10.111.132.229是集群提供的cluster-ip,可以用pod内部端口访问,而192.168.110.186~192.168.110.188是k8s集群的节点IP,我们可以使用任意节点来访问。

实现从外部登录

这个端口虽然对外暴露出来了,但是我们并不能直接使用TCP的方式登录上去。除了default用户,clickhouse-operator还为我们提供了一个clickhouse_operator的用户,默认密码是clickhouse_operator_password,但是目前这两个用户都无法从外面访问。

su01:~/chenyc/ck/ch # clickhouse-client -m -h 192.168.110.186 --port 39000 ClickHouse client version 23.3.1.2823 (official build). Connecting to 192.168.110.186:39000 as user default. Password for user (default): Connecting to 192.168.110.186:39000 as user default. Code: 516. DB::Exception: Received from 192.168.110.186:39000. DB::Exception: default: Authentication failed: password is incorrect, or there is no user with such name. If you have installed ClickHouse and forgot password you can reset it in the configuration file. The password for default user is typically located at /etc/clickhouse-server/users.d/default-password.xml and deleting this file will reset the password. See also /etc/clickhouse-server/users.xml on the server where ClickHouse is installed. . (AUTHENTICATION_FAILED) su01:~/chenyc/ck/ch # clickhouse-client -m -h 192.168.110.186 --port 39000 -u clickhouse_operator --password clickhouse_operator_password ClickHouse client version 23.3.1.2823 (official build). Connecting to 192.168.110.186:39000 as user clickhouse_operator. Code: 516. DB::Exception: Received from 192.168.110.186:39000. DB::Exception: clickhouse_operator: Authentication failed: password is incorrect, or there is no user with such name.. (AUTHENTICATION_FAILED)

这两个用户肯定是有效的,我们可以从pod内部登录访问:

su01:~/chenyc/ck/ch # kubectl exec -it chi-svc-cluster-0-0-0 -- /bin/bash root@chi-svc-cluster-0-0-0:/# clickhouse-client -m ClickHouse client version 23.10.5.20 (official build). Connecting to localhost:9000 as user default. Connected to ClickHouse server version 23.10.5 revision 54466. Warnings: * Linux transparent hugepages are set to "always". Check /sys/kernel/mm/transparent_hugepage/enabled * Delay accounting is not enabled, OSIOWaitMicroseconds will not be gathered. Check /proc/sys/kernel/task_delayacct chi-svc-cluster-0-0-0.chi-svc-cluster-0-0.default.svc.cluster.local :)

为什么会如此,我们打开用户的配置文件:

root@chi-svc-cluster-0-0-0:/# cat /etc/clickhouse-server/users.d/chop-generated-users.xml 10.0.2.45 716b36073a90c6fe1d445ac1af85f4777c5b7a155cea359961826a030513e448 clickhouse_operator (chi-svc-[^.]+\d+-\d+|clickhouse\-svc)\.default\.svc\.cluster\.local$ ::1 127.0.0.1 default default

可以看到,clickhouse_operator用户仅仅对内部ip开放,而default用户仅仅对本地回环开放以及hostname满足内部正则表达式规则的主机名开放,所以外面是无法登录的。那这样我们仍然用不了。

解决方案仍然有两种:

增加一个普通用户,该用户可以用来从外部访问去掉default用户和clickhouse_operator用户的权限控制

我们先看第一种方法。

我们可以在configuration里增加users的信息,比如我们增加一个叫chenyc的用户:

apiVersion: "clickhouse.altinity.com/v1" kind: "ClickHouseInstallation" metadata: name: "user" spec: configuration: users: chenyc/network/ip: "::/0" chenyc/password: qwerty chenyc/profile: default defaults: templates: serviceTemplate: service-template templates: serviceTemplates: - name: service-template generateName: chendpoint-{chi} spec: ports: - name: http port: 8123 nodePort: 38123 targetPort: 8123 - name: tcp port: 9000 nodePort: 39000 targetPort: 9000 type: NodePort

查看配置文件:

su01:~/chenyc/ck/ch # kubectl exec -it chi-user-cluster-0-0-0 -- cat /etc/clickhouse-server/users.d/chop-generated-users.xml ::/0 (chi-user-[^.]+\d+-\d+|clickhouse\-user)\.default\.svc\.cluster\.local$ ::1 127.0.0.1 65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5 default default 10.0.2.45 716b36073a90c6fe1d445ac1af85f4777c5b7a155cea359961826a030513e448 clickhouse_operator (chi-user-[^.]+\d+-\d+|clickhouse\-user)\.default\.svc\.cluster\.local$ ::1 127.0.0.1 default default

但是我们发现仍然访问不了,因为仍然有下面这段权限限制:

(chi-user-[^.]+\d+-\d+|clickhouse\-user)\.default\.svc\.cluster\.local$ ::1 127.0.0.1

似乎第一种方案已经走入死胡同了,接下来我们来尝试第二种方式。

我们先看看clickhouse-operator源码中是如何处理用户的访问权限的。

func (n *Normalizer) normalizeConfigurationUserEnsureMandatorySections(users *chiV1.Settings, username string) { chopUsername := chop.Config().ClickHouse.Access.Username // // Ensure each user has mandatory sections: // // 1. user/profile // 2. user/quota // 3. user/networks/ip // 4. user/networks/host_regexp profile := chop.Config().ClickHouse.Config.User.Default.Profile quota := chop.Config().ClickHouse.Config.User.Default.Quota ips := append([]string{}, chop.Config().ClickHouse.Config.User.Default.NetworksIP...) regexp := CreatePodHostnameRegexp(n.ctx.chi, chop.Config().ClickHouse.Config.Network.HostRegexpTemplate) // Some users may have special options switch username { case defaultUsername: ips = append(ips, n.ctx.options.DefaultUserAdditionalIPs...) if !n.ctx.options.DefaultUserInsertHostRegex { regexp = "" } case chopUsername: ip, _ := chop.Get().ConfigManager.GetRuntimeParam(chiV1.OPERATOR_POD_IP) profile = chopProfile quota = "" ips = []string{ip} regexp = "" } // Ensure required values are in place and apply non-empty values in case no own value(s) provided if profile != "" { users.SetIfNotExists(username+"/profile", chiV1.NewSettingScalar(profile)) } if quota != "" { users.SetIfNotExists(username+"/quota", chiV1.NewSettingScalar(quota)) } if len(ips) > 0 { users.Set(username+"/networks/ip", chiV1.NewSettingVector(ips).MergeFrom(users.Get(username+"/networks/ip"))) } if regexp != "" { users.SetIfNotExists(username+"/networks/host_regexp", chiV1.NewSettingScalar(regexp)) } } default用户

根据DefaultUserInsertHostRegex变量来判断是否要配置host_regexp, 而该变量默认是true:

// NewNormalizerOptions creates new NormalizerOptions func NewNormalizerOptions() *NormalizerOptions { return &NormalizerOptions{ DefaultUserInsertHostRegex: true, } }

ip的限制则取决于配置的additional ip列表。

因此,我们只需要将additional IP以及host_regexp的规则在clickhouse_operator的yaml中去掉即可。

chop用户

chop就是clickhouse_operator用户,它的ip限制主要取决于OPERATOR_POD_IP环境变量。而该环境变量可以通过clickhouse_operator的yaml传入,它默认是取的pod的IP,我们将其设置成::/0, 即可所有人都能访问了。

ip, _ := chop.Get().ConfigManager.GetRuntimeParam(chiV1.OPERATOR_POD_IP) 其他普通用户 ips := append([]string{}, chop.Config().ClickHouse.Config.User.Default.NetworksIP...) regexp := CreatePodHostnameRegexp(n.ctx.chi, chop.Config().ClickHouse.Config.Network.HostRegexpTemplate)

同样也是修改yaml。

有了以上的基础,我们直接修改yaml:

原始yaml:

user: # Default settings for user accounts, created by the operator. # IMPORTANT. These are not access credentials or settings for 'default' user account, # it is a template for filling out missing fields for all user accounts to be created by the operator, # with the following EXCEPTIONS: # 1. 'default' user account DOES NOT use provided password, but uses all the rest of the fields. # Password for 'default' user account has to be provided explicitly, if to be used. # 2. CHOP user account DOES NOT use: # - profile setting. It uses predefined profile called 'clickhouse_operator' # - quota setting. It uses empty quota name. # - networks IP setting. Operator specifies 'networks/ip' user setting to match operators' pod IP only. # - password setting. Password for CHOP account is used from 'clickhouse.access.*' section default: # Default values for ClickHouse user account(s) created by the operator # 1. user/profile - string # 2. user/quota - string # 3. user/networks/ip - multiple strings # 4. user/password - string # These values can be overwritten on per-user basis. profile: "default" quota: "default" networksIP: - "::1" - "127.0.0.1" password: "default" ################################################ ## ## Configuration Network Section ## ################################################ network: # Default host_regexp to limit network connectivity from outside hostRegexpTemplate: "(chi-{chi}-[^.]+\\d+-\\d+|clickhouse\\-{chi})\\.{namespace}\\.svc\\.cluster\\.local$"

修改后yaml:

user: # Default settings for user accounts, created by the operator. # IMPORTANT. These are not access credentials or settings for 'default' user account, # it is a template for filling out missing fields for all user accounts to be created by the operator, # with the following EXCEPTIONS: # 1. 'default' user account DOES NOT use provided password, but uses all the rest of the fields. # Password for 'default' user account has to be provided explicitly, if to be used. # 2. CHOP user account DOES NOT use: # - profile setting. It uses predefined profile called 'clickhouse_operator' # - quota setting. It uses empty quota name. # - networks IP setting. Operator specifies 'networks/ip' user setting to match operators' pod IP only. # - password setting. Password for CHOP account is used from 'clickhouse.access.*' section default: # Default values for ClickHouse user account(s) created by the operator # 1. user/profile - string # 2. user/quota - string # 3. user/networks/ip - multiple strings # 4. user/password - string # These values can be overwritten on per-user basis. profile: "default" quota: "default" password: "default" ################################################ ## ## Configuration Network Section ## ################################################

修改前yaml:

env: # Pod-specific # spec.nodeName: ip-172-20-52-62.ec2.internal - name: OPERATOR_POD_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName # metadata.name: clickhouse-operator-6f87589dbb-ftcsf - name: OPERATOR_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name # metadata.namespace: kube-system - name: OPERATOR_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace # status.podIP: 100.96.3.2 - name: OPERATOR_POD_IP valueFrom: fieldRef: fieldPath: status.podIP # spec.serviceAccount: clickhouse-operator # spec.serviceAccountName: clickhouse-operator - name: OPERATOR_POD_SERVICE_ACCOUNT valueFrom: fieldRef: fieldPath: spec.serviceAccountName

修改后yaml:

env: # Pod-specific # spec.nodeName: ip-172-20-52-62.ec2.internal - name: OPERATOR_POD_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName # metadata.name: clickhouse-operator-6f87589dbb-ftcsf - name: OPERATOR_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name # metadata.namespace: kube-system - name: OPERATOR_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace # status.podIP: 100.96.3.2 - name: OPERATOR_POD_IP value: "::/0" #valueFrom: # fieldRef: # fieldPath: status.podIP # spec.serviceAccount: clickhouse-operator # spec.serviceAccountName: clickhouse-operator - name: OPERATOR_POD_SERVICE_ACCOUNT valueFrom: fieldRef: fieldPath: spec.serviceAccountName

以上内容修改完成后,重新apply clickhouse-operator。实际上,chop的用户我们也可以通过yaml去修改。比如我们将用户改成eoi,密码改成123456:

apiVersion: v1 kind: Secret metadata: name: clickhouse-operator namespace: kube-system labels: clickhouse.altinity.com/chop: 0.21.3 app: clickhouse-operator type: Opaque stringData: username: eoi password: "123456"

再次部署clickhouse, 查看配置文件:

::/0 65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5 default default ::/0 default default ::/0 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 clickhouse_operator

从配置文件来看一切满足预期,我们尝试登录一下:

default用户可正常登录:

su01:~/chenyc/ck/ch # clickhouse-client -h 192.168.110.186 --port 39000 ClickHouse client version 23.3.1.2823 (official build). Connecting to 192.168.110.186:39000 as user default. Connected to ClickHouse server version 23.10.5 revision 54466. ClickHouse client version is older than ClickHouse server. It may lack support for new features. Warnings: * Linux transparent hugepages are set to "always". Check /sys/kernel/mm/transparent_hugepage/enabled * Delay accounting is not enabled, OSIOWaitMicroseconds will not be gathered. Check /proc/sys/kernel/task_delayacct chi-user-cluster-0-0-0.chi-user-cluster-0-0.default.svc.cluster.local :) exit Bye.

chop用户:

su01:~/chenyc/ck/ch # clickhouse-client -h 192.168.110.186 --port 39000 -u eoi --password 123456 ClickHouse client version 23.3.1.2823 (official build). Connecting to 192.168.110.186:39000 as user eoi. Connected to ClickHouse server version 23.10.5 revision 54466. ClickHouse client version is older than ClickHouse server. It may lack support for new features. Warnings: * Linux transparent hugepages are set to "always". Check /sys/kernel/mm/transparent_hugepage/enabled * Delay accounting is not enabled, OSIOWaitMicroseconds will not be gathered. Check /proc/sys/kernel/task_delayacct chi-user-cluster-0-0-0.chi-user-cluster-0-0.default.svc.cluster.local :) exit Bye.

chenyc用户(自定义普通用户):

su01:~/chenyc/ck/ch # clickhouse-client -h 192.168.110.186 --port 39000 -u chenyc --password qwerty ClickHouse client version 23.3.1.2823 (official build). Connecting to 192.168.110.186:39000 as user chenyc. Connected to ClickHouse server version 23.10.5 revision 54466. ClickHouse client version is older than ClickHouse server. It may lack support for new features. Warnings: * Linux transparent hugepages are set to "always". Check /sys/kernel/mm/transparent_hugepage/enabled * Delay accounting is not enabled, OSIOWaitMicroseconds will not be gathered. Check /proc/sys/kernel/task_delayacct chi-user-cluster-0-0-0.chi-user-cluster-0-0.default.svc.cluster.local :) exit Bye.

以上就是通过修改operator的yaml,实现外部登录的过程。当然,像default用户、chop用户等有特殊含义的用户,实际使用时是不建议暴露出来让外界使用的。建议创建一个普通用户能让外界访问即可。

storageclass部署

clickhouse作为一个数据库,最关键的自然是数据持久化的问题。那就意味着我们必须要使用PVC来指定持久化路径。下面是一个指定了持久化目录的例子:

apiVersion: "clickhouse.altinity.com/v1" kind: "ClickHouseInstallation" metadata: name: "aimeter" spec: defaults: templates: serviceTemplate: service-template podTemplate: pod-template dataVolumeClaimTemplate: volume-claim logVolumeClaimTemplate: volume-claim templates: serviceTemplates: - name: service-template generateName: chendpoint-{chi} spec: ports: - name: http port: 8123 nodePort: 38123 targetPort: 8123 - name: tcp port: 9000 nodePort: 39000 targetPort: 9000 type: NodePort podTemplates: - name: pod-template spec: containers: - name: clickhouse imagePullPolicy: Always image: yandex/clickhouse-server:latest volumeMounts: - name: volume-claim mountPath: /var/lib/clickhouse - name: volume-claim mountPath: /var/log/clickhouse-server volumeClaimTemplates: - name: volume-claim spec: accessModes: - ReadWriteOnce resources: requests: storage: 100Gi

前面提到过,clickhouse-operator默认是在云环境运行的。上面这段yaml在云环境是可以直接运行的,但是在私有k8s环境运行会报错。可以看到,其运行状态是pending。

su01:~/chenyc/ck/ch # kubectl get pod NAME READY STATUS RESTARTS AGE chi-aimeter-cluster-0-0-0 0/2 Pending 0 6s ckman-6d8cd8fbdc-mlsmb 1/1 Running 0 5d4h

使用describe去查看具体信息,得到如下报错:

Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 68s (x2 over 70s) default-scheduler 0/3 nodes are available: pod has unbound immediate PersistentVolumeClaims. preemption: 0/3 nodes are available: 3 No preemption victims found for incoming pod..

以上错误是因为没有可用的持久化卷。我们可以通过自建nfs的方式提供一个PV来供挂载。

我们先在一台服务器上创建nfs service。

# 安装nfs以及rpc服务 yum install nfs-utils rpcbind -y # 修改 /etc/exports /data01/nfs 192.168.110.0/24(insecure,rw,sync,no_subtree_check,no_root_squash) exportfs -r #使配置生效 #重启nfs服务: service rpcbind restart ;service nfs restart

创建provisioner、storageclass:

#### 权限配置 --- apiVersion: v1 kind: ServiceAccount metadata: name: nfs-common-provisioner namespace: default --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: nfs-common-provisioner-runner rules: - apiGroups: [""] resources: ["nodes"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "delete"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["create", "update", "patch"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: run-nfs-common-provisioner subjects: - kind: ServiceAccount name: nfs-common-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-common-provisioner-runner apiGroup: rbac.authorization.k8s.io --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: leader-locking-nfs-common-provisioner namespace: default rules: - apiGroups: [""] resources: ["endpoints"] verbs: ["get", "list", "watch", "create", "update", "patch"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: leader-locking-nfs-common-provisioner namespace: default subjects: - kind: ServiceAccount name: nfs-common-provisioner namespace: default roleRef: kind: Role name: leader-locking-nfs-common-provisioner apiGroup: rbac.authorization.k8s.io #### class --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-common # 配置pvc使用 provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # 指定一个供应商的名字 与 PROVISIONER_NAME 保持一致 # or choose another name, 必须匹配 deployment 的 env PROVISIONER_NAME' parameters: archiveOnDelete: "false" # 删除 PV 的时候,PV 中的内容是否备份 #### 部署deploy --- apiVersion: apps/v1 kind: Deployment metadata: name: nfs-common-provisioner labels: app: nfs-common-provisioner namespace: default spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-common-provisioner template: metadata: labels: app: nfs-common-provisioner spec: serviceAccountName: nfs-common-provisioner containers: - name: nfs-common-provisioner image: ccr.ccs.tencentyun.com/gcr-containers/nfs-subdir-external-provisioner:v4.0.2 volumeMounts: - name: nfs-common-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: k8s-sigs.io/nfs-subdir-external-provisioner - name: NFS_SERVER value: 192.168.110.10 # NFS 服务器的地址 - name: NFS_PATH value: /data01/nfs # NFS 服务器的共享目录 volumes: - name: nfs-common-root nfs: server: 192.168.110.10 path: /data01/nfs

应用:

su01:~/chenyc/ck/ch # kubectl apply -f storageclass.yaml serviceaccount/nfs-common-provisioner created clusterrole.rbac.authorization.k8s.io/nfs-common-provisioner-runner created clusterrolebinding.rbac.authorization.k8s.io/run-nfs-common-provisioner created role.rbac.authorization.k8s.io/leader-locking-nfs-common-provisioner created rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-common-provisioner created storageclass.storage.k8s.io/nfs-common created deployment.apps/nfs-common-provisioner created

成功应该可以查到以下信息:

su01:~/chenyc/ck/ch # kubectl get pod NAME READY STATUS RESTARTS AGE chi-aimeter-cluster-0-0-0 0/2 Pending 0 16m ckman-6d8cd8fbdc-mlsmb 1/1 Running 0 5d4h nfs-common-provisioner-594bc9d55d-clhvl 1/1 Running 0 5m51s su01:~/chenyc/ck/ch # kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE nfs-common k8s-sigs.io/nfs-subdir-external-provisioner Delete Immediate false 5m57s

我们将上述的yaml的pvc挂载到这个sc上:

volumeClaimTemplates: - name: volume-claim spec: accessModes: - ReadWriteOnce storageClassName: "nfs-common" resources: requests: storage: 100Gi

再次查看,部署成功:

su01:~/chenyc/ck/ch # kubectl get pod NAME READY STATUS RESTARTS AGE chi-aimeter-cluster-0-0-0 2/2 Running 0 117s ckman-6d8cd8fbdc-mlsmb 1/1 Running 0 5d4h nfs-common-provisioner-594bc9d55d-clhvl 1/1 Running 0 10m su01:~/chenyc/ck/ch # kubectl get sts NAME READY AGE chi-aimeter-cluster-0-0 1/1 2m1s su01:~/chenyc/ck/ch # kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-e23ae072-5e95-415c-9628-3ea7fb1ed4d6 100Gi RWO Delete Bound default/volume-claim-chi-aimeter-cluster-0-0-0 nfs-common 2m4s su01:~/chenyc/ck/ch # kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE volume-claim-chi-aimeter-cluster-0-0-0 Bound pvc-e23ae072-5e95-415c-9628-3ea7fb1ed4d6 100Gi RWO nfs-common 2m8s

从nfs原始目录可以看到已经有目录挂载在上面:

zookeeper部署

clickhouse集群是依赖zookeeper的。clickhouse-operator项目官方很贴心地提供了pv方式部署以及emptyDir方式部署zookeeper的方案,且都提供了单节点和三节点的部署yaml。

我们这里以单节点持久化的场景为例:

# Setup Service to provide access to Zookeeper for clients apiVersion: v1 kind: Service metadata: # DNS would be like zookeeper.zoons name: zookeeper labels: app: zookeeper spec: type: NodePort ports: - port: 2181 name: client - port: 7000 name: prometheus selector: app: zookeeper what: node --- # Setup Headless Service for StatefulSet apiVersion: v1 kind: Service metadata: # DNS would be like zookeeper-0.zookeepers.etc name: zookeepers labels: app: zookeeper spec: ports: - port: 2888 name: server - port: 3888 name: leader-election clusterIP: None selector: app: zookeeper what: node --- # Setup max number of unavailable pods in StatefulSet apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: zookeeper-pod-disruption-budget spec: selector: matchLabels: app: zookeeper maxUnavailable: 1 --- # Setup Zookeeper StatefulSet # Possible params: # 1. replicas # 2. memory # 3. cpu # 4. storage # 5. storageClassName # 6. user to run app apiVersion: apps/v1 kind: StatefulSet metadata: # nodes would be named as zookeeper-0, zookeeper-1, zookeeper-2 name: zookeeper labels: app: zookeeper spec: selector: matchLabels: app: zookeeper serviceName: zookeepers replicas: 1 updateStrategy: type: RollingUpdate podManagementPolicy: OrderedReady template: metadata: labels: app: zookeeper what: node annotations: prometheus.io/port: '7000' prometheus.io/scrape: 'true' spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: "app" operator: In values: - zookeeper # TODO think about multi-AZ EKS # topologyKey: topology.kubernetes.io/zone topologyKey: "kubernetes.io/hostname" containers: - name: kubernetes-zookeeper imagePullPolicy: IfNotPresent image: "docker.io/zookeeper:3.8.1" resources: requests: memory: "512M" cpu: "1" limits: memory: "4Gi" cpu: "2" ports: - containerPort: 2181 name: client - containerPort: 2888 name: server - containerPort: 3888 name: leader-election - containerPort: 7000 name: prometheus env: - name: SERVERS value: "1" # See those links for proper startup settings: # https://github.com/kow3ns/kubernetes-zookeeper/blob/master/docker/scripts/start-zookeeper # https://clickhouse.yandex/docs/en/operations/tips/#zookeeper # https://github.com/ClickHouse/ClickHouse/issues/11781 command: - bash - -x - -c - | HOST=`hostname -s` && DOMAIN=`hostname -d` && CLIENT_PORT=2181 && SERVER_PORT=2888 && ELECTION_PORT=3888 && PROMETHEUS_PORT=7000 && ZOO_DATA_DIR=/var/lib/zookeeper/data && ZOO_DATA_LOG_DIR=/var/lib/zookeeper/datalog && { echo "clientPort=${CLIENT_PORT}" echo 'tickTime=2000' echo 'initLimit=300' echo 'syncLimit=10' echo 'maxClientCnxns=2000' echo 'maxTimeToWaitForEpoch=2000' echo 'maxSessionTimeout=60000000' echo "dataDir=${ZOO_DATA_DIR}" echo "dataLogDir=${ZOO_DATA_LOG_DIR}" echo 'autopurge.snapRetainCount=10' echo 'autopurge.purgeInterval=1' echo 'preAllocSize=131072' echo 'snapCount=3000000' echo 'leaderServes=yes' echo 'standaloneEnabled=false' echo '4lw.commands.whitelist=*' echo 'metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider' echo "metricsProvider.httpPort=${PROMETHEUS_PORT}" echo "skipACL=true" echo "fastleader.maxNotificationInterval=10000" } > /conf/zoo.cfg && { echo "zookeeper.root.logger=CONSOLE" echo "zookeeper.console.threshold=INFO" echo "log4j.rootLogger=\${zookeeper.root.logger}" echo "log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender" echo "log4j.appender.CONSOLE.Threshold=\${zookeeper.console.threshold}" echo "log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout" echo "log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} - %-5p [%t:%C{1}@%L] - %m%n" } > /conf/log4j.properties && echo 'JVMFLAGS="-Xms128M -Xmx4G -XX:ActiveProcessorCount=8 -XX:+AlwaysPreTouch -Djute.maxbuffer=8388608 -XX:MaxGCPauseMillis=50"' > /conf/java.env && if [[ $HOST =~ (.*)-([0-9]+)$ ]]; then NAME=${BASH_REMATCH[1]} && ORD=${BASH_REMATCH[2]}; else echo "Failed to parse name and ordinal of Pod" && exit 1; fi && mkdir -pv ${ZOO_DATA_DIR} && mkdir -pv ${ZOO_DATA_LOG_DIR} && whoami && chown -Rv zookeeper "$ZOO_DATA_DIR" "$ZOO_DATA_LOG_DIR" && export MY_ID=$((ORD+1)) && echo $MY_ID > $ZOO_DATA_DIR/myid && for (( i=1; i> /conf/zoo.cfg; done && if [[ $SERVERS -eq 1 ]]; then echo "group.1=1" >> /conf/zoo.cfg; else echo "group.1=1:2:3" >> /conf/zoo.cfg; fi && for (( i=1; i> /conf/zoo.cfg; done && zkServer.sh start-foreground readinessProbe: exec: command: - bash - -c - ' IFS=; MNTR=$(exec 3/dev/tcp/127.0.0.1/2181 ; printf "mntr" >&3 ; tee


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


    图片新闻

    实验室药品柜的特性有哪些
    实验室药品柜是实验室家具的重要组成部分之一,主要
    小学科学实验中有哪些教学
    计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
    实验室各种仪器原理动图讲
    1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
    高中化学常见仪器及实验装
    1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
    微生物操作主要设备和器具
    今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
    浅谈通风柜使用基本常识
     众所周知,通风柜功能中最主要的就是排气功能。在

    专题文章

      CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭